<?php
/** 
 * @package AMFramework
 * @subpackage Core
 * @author Marcu Alexandru
 * @version 1.0 $Build 305b  
 */
defined('_INDEX') or die('Restricted');

class Amfw_Object extends Amfw_Primitive {
	// Public =============================================================
	public function init() {
		// Alias ce permite initializarea obiectului din afara lui;
		// nu se va permite insa pornirea selectiva a anumitor metode din afara obiectului,
		// asa ca vom initializa toate metodele __init_all()
		$this->__initAll();
	} //TODO: Optimizarea metodelor de initializare / initializare ordonata,etc

	public function set($var_name, $value) {
		// If we've got a null argument we'll return false;
		if($value !== null) {
			// First we verify if the property exists
			if(property_exists($this,$var_name)):
				$prev = $this->$var_name;
				$this->$var_name = $value;
				return $prev;
				endif;
			// If we don't have a property with this name perhaps we can use a setter
			$m_set = 'set'.$var_name;
			if(method_exists($this,$m_set)):
				return $this->$m_set($value);
				endif;
		}
		return false;
	}

	public function get($var_name, $default = null) {
		// Initial metoda va cauta o proprietate cu numele primit
		if(isset($this->$var_name))
			return $this->$var_name;
		// Daca nu exista o proprietate se cauta o metoda getter
		// ce poate fi apelata
		$m_get = 'get'.$var_name;
		if(method_exists($this, $m_get))
			return $this->$m_get();
		// Daca se ajunge pana aici, intoarcem valoarea implicita (argument)
		return $default;
	}
	
	// Protected ===========================================================
	protected function mirror( $object ) {
		if(!is_object( $object )) return false;

		$class_name 	= get_class( $object );
		$prefix 		= substr($class_name, 0, strpos($class_name, '_'));
		$parent_class 	= get_parent_class( $object );

		return array
				(	'name' => $class_name, 
					'prefix' => $prefix, 
					'parent' => $parent_class
				);
	}
	
	protected function __init() 
	{
		// Daca nu se primes argumente, se initializeaza toate metodele
		// de initializare, altfel se incearca initializarea metodelor definite
		$args = func_get_args();
		if(!empty($args)) 
			$this->__initMethods($args);
		else $this->__initAll();
	}
	
	protected function __initAll($except = array()) 
	{
		// Metoda ce poate fi rulata in constructor, care ruleaza
		// automat toate metodele de initializare
		$methods = get_class_methods($this);

		// Daca get_class_methods intoarce null, atunci metoda va intoarce
		// false, pentru a permite prinderea erorii
		if(!isset($methods))
			return false;

		// Adaugat in 1/04/2011 -- posibilitatea de a excepta anumite metode de la initializare
		// implicita daca ele au fost deja initializate explicit
		if(!empty($except)) {
			if(!is_array($except)) 
				$except = (array) $except;

			for($i =0, $n = count($except); $i < $n; $i++ ) {
				$tmp = '_init'.$except[$i];
				
				foreach($methods as $key => $value) {
					if($tmp == $value) {
						Amfw_Debug::toJournal($value.'() has already been initialized and was set for exception.');
						unset($methods[$key]);
					}//~!if
				}//~!foreach
			}//~!for
		}//~!empty($except) -- nu se intra daca nu sunt exceptii

		// Rularea pe rand a metodelor de initializare
		// Prefixul este case-Insensitive
		foreach($methods as $m_name) {
			if(stripos($m_name,'_init') === 0)
				$this->$m_name();
		}
	}

	protected function __initMethods() {
		$names = func_get_args();

		// Daca in loc de enumerarea argumentelor acestea sunt trimise
		// intr-un array, se va incerca citirea lor oricum
		if(count($names) == 1 && is_array($names[0])) {
			$names = $names[0];
		}

		// Se adauga pentru fiecare nume prefixul si se incearca rularea
		// metodei
		foreach($names as $name) {
			$method = '_init'.$name;
			if(method_exists($this,$method))
				$this->$method();
		}
	}
}